package legumes.client.ui.basket.slate;

import legumes.client.evt.customer.CustomerOrderChangedEvent;
import legumes.client.evt.manager.EventBusManager;
import legumes.client.resources.PNResources;
import legumes.client.services.callbacks.SaveStallCallback;
import legumes.client.services.util.rpc.RPCCallSequencer;
import legumes.client.ui.widgets.form.item.QuantityFloatItem;
import legumes.client.ui.widgets.form.item.QuantityUnitFormItemFactory;
import legumes.client.ui.widgets.utils.Formatters;
import legumes.shared.domain.OnSaleProduct;
import legumes.shared.domain.OrderPart;
import legumes.shared.domain.OrderPartProductItem;
import legumes.shared.domain.Quantity;
import legumes.shared.domain.Stall;
import legumes.shared.domain.Unit;

import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.Element;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.ui.FlexTable;
import com.google.gwt.user.client.ui.HTML;
import com.smartgwt.client.types.Alignment;
import com.smartgwt.client.widgets.Canvas;
import com.smartgwt.client.widgets.WidgetCanvas;
import com.smartgwt.client.widgets.Window;
import com.smartgwt.client.widgets.events.CloseClickHandler;
import com.smartgwt.client.widgets.events.CloseClientEvent;
import com.smartgwt.client.widgets.form.DynamicForm;
import com.smartgwt.client.widgets.form.fields.ButtonItem;
import com.smartgwt.client.widgets.form.fields.FormItem;
import com.smartgwt.client.widgets.form.fields.events.ClickEvent;
import com.smartgwt.client.widgets.form.fields.events.ClickHandler;
import com.smartgwt.client.widgets.layout.HLayout;

public class ProductCustomerEditionWindow extends Window {

	private FlexTable flexTableOutsideBasket;
	private OnSaleProduct product;
	private OrderPart op;
	private OrderPartProductItem oldOppi;
	private ButtonItem biDel;
	private ButtonItem biValidate;
	private QuantityFloatItem tiUserQuantity;
	private FormItem fiUserQuantityUnit;
	private DynamicForm form;
	private Stall stall;
	
	public ProductCustomerEditionWindow(OnSaleProduct product_, Stall stall_, OrderPart op_) {
		super();
		product = product_;
		stall = stall_;
		op=op_;
		setWidth(480);
		setHeight(200);
		

		setTitle("<img src=\""
				+ PNResources.INSTANCE.shoppingChartIcon().getURL()
				+ "\" />&nbsp;" + product.getProduct().getName());

		setShowCloseButton(true);
		setShowMinimizeButton(false);
		setCanDrag(true);
		setCanDragReposition(true);
		setIsModal(true);
		setShowModalMask(true);  
		setAutoCenter(true);
		addCloseClickHandler(new CloseClickHandler() {  
            public void onCloseClick(CloseClientEvent event) {  
                destroy();  
            }  
        });  
		buildPanel();
		initData();
		show();
		tiUserQuantity.focusInItem();
	}

	private void initData() {
		oldOppi = op.findOrderPartProductItemFor(product.getProduct().getName());
		if(oldOppi != null){
			fiUserQuantityUnit.setValue( new HTML(oldOppi.getQuantity().getUnit()).getHTML() );
			tiUserQuantity.setValue(oldOppi.getQuantity().getValue());
		} else { 
			fiUserQuantityUnit.setValue( new HTML(product.getPrice().getQuantity().getUnitAsEnum().getDisplayName()).getHTML() );
			tiUserQuantity.setValue( product.getPrice().getQuantity().getValue() );
			biDel.setVisible(false);
			biValidate.setColSpan(2);
		}
	}

	private void buildPanel() {
		HLayout mainLayout = new HLayout();
		mainLayout.setMargin(10);
		
		mainLayout.setMembers( buildProductPanel(), buildFormPanel());
		
		addItem(mainLayout);
	}
	
	private Canvas buildFormPanel(){
		form = new DynamicForm();
		form.setPadding(5);  
		form.setWidth("*");
		form.setLayoutAlign(Alignment.CENTER);
		
		tiUserQuantity = new QuantityFloatItem();		
		Unit quantityUnit = product.getPrice().getQuantity().getUnitAsEnum();
    	fiUserQuantityUnit = QuantityUnitFormItemFactory.createFormItem(quantityUnit);
		
    	
    	biValidate = new ButtonItem("AddToBasket", "Ajouter au panier");
    	biValidate.setAutoFit(true);
    	biValidate.setColSpan(1);
    	biValidate.setAlign(Alignment.CENTER);
    	biValidate.setStartRow(true);
    	biValidate.setEndRow(false);
    	biValidate.setIcon( PNResources.INSTANCE.addIcon().getURL() );
    	biValidate.addClickHandler( createClickhandler(true) );
    	
    	biDel = new ButtonItem("RemoveFromBasket", "Retirer du panier");
    	biDel.setColSpan(1);
    	biDel.setIcon( PNResources.INSTANCE.deleteIcon().getURL() );
    	biDel.setAlign(Alignment.CENTER);
    	biDel.setStartRow(false);
    	biDel.setEndRow(false);
    	biDel.addClickHandler( new ClickHandler() {
			
			@Override
			public void onClick(ClickEvent event) {
				if(oldOppi!=null){
					op.getOrderPartProductItems().remove(oldOppi);
					EventBusManager.getInstance().getEventBus().fireEvent(
	                			new CustomerOrderChangedEvent(false , computeOldPrice()));
	            	updateProduct(false);
				}
            	ProductCustomerEditionWindow.this.destroy();
			}
		});
    	
    	ButtonItem biCancel = new ButtonItem("CancelAddToBasket", "Annuler");
    	biCancel.setColSpan(2);
    	biCancel.setAutoFit(true);
    	biCancel.setAlign(Alignment.CENTER);
    	biCancel.setStartRow(true);
    	biCancel.setEndRow(false);
    	biCancel.setIcon( PNResources.INSTANCE.cancelIcon().getURL() );
    	biCancel.addClickHandler(new ClickHandler() {
			
			@Override
			public void onClick(ClickEvent event) {
				ProductCustomerEditionWindow.this.destroy();
			}
		});
    	
    	form.setFields(tiUserQuantity, fiUserQuantityUnit, biValidate, biDel, biCancel);

        return form;
	}
	
	private Canvas buildProductPanel(){
		flexTableOutsideBasket = new FlexTable();

		String price = Formatters.formatPrice(product.getPrice(), true);
		String name = product.getProduct().getName();
		String quantity = Formatters.formatQuantity(product.getPrice().getQuantity());
		
		String quantityUnit = product.getPrice().getQuantity().getUnitAsEnum().getDisplayName();
		
		String appendSpacesToProductName = "";
		if(name.length()<=8){
			appendSpacesToProductName = "&nbsp;&nbsp;&nbsp;";
		}
		String priceTxt = price + " / " + quantity + quantityUnit;
		String appendSpacesToPriceTxt = "";
		if(priceTxt.length()<=16){
			appendSpacesToPriceTxt = "&nbsp;&nbsp;&nbsp;";
		}
		
		flexTableOutsideBasket.setHTML(0, 0,
				//"<div class=\"" + glueCagette + "\">" +
				"<div class=\"slate\">"
				+ "<div id=\"shoppingChartGreen." + name + "\" class=\"productInChartGreenFlag \"></div>"
				+ "<div class=\"slateTxt\">" + appendSpacesToProductName
				+ name + "<BR/>" + "<span class=\"priceTxt\">" + appendSpacesToPriceTxt
				+ price + " / " + quantity + quantityUnit
				+ "</span>" + "</div></div></div>");
		flexTableOutsideBasket.setHTML(1, 0, 
				//"<div class=\"" + glueCagette + "\">" +
				"<div class=\"borderCagette\">" +								
				"<div class=\"" + PNResources.PRODUCT_NAME_CSS_PREFIX + "commonVegetable " + PNResources.PRODUCT_NAME_CSS_PREFIX + name.toLowerCase() + "\">" +
				"</div></div></div>"
		);
		
		return new WidgetCanvas(flexTableOutsideBasket);
	}
	
	private ClickHandler createClickhandler(final boolean updateBill_){
		return new ClickHandler() {
			
			
			private float computePrice(Unit oldQuantiteUnitEnum_, Unit newQuantiteUnitEnum_,
					float newQuantite_, float oldQuantite_, float oldPrice_){

            	float coef = 1.0f;
            	if(oldQuantiteUnitEnum_.equals(Unit.KG) 
            			&& newQuantiteUnitEnum_.equals(Unit.G)){
            		coef = 1/1000f;
            	} else if (oldQuantiteUnitEnum_.equals(Unit.G) 
            			&& newQuantiteUnitEnum_.equals(Unit.KG)){
            		coef = 1000f;
            	}
            	
            	float price = product.getPrice().getAmount();
            	return price*newQuantite_*coef/oldQuantite_ - oldPrice_;
			}
			
			
			private void updateOrder(Unit oldQuantiteUnitEnum_, Unit newQuantiteUnitEnum_,
					float newQuantite_, float oldQuantite_){
				String productName = product.getProduct().getName();
				OrderPartProductItem oppi = op.findOrderPartProductItemFor(productName);
            	if( oppi == null ){
            		oppi = new OrderPartProductItem();
            		OnSaleProduct product = stall.findOnSaleProduct(productName);
                	oppi.setOnSaleProduct(product);
            		op.addOrderPartProductItem(oppi);
            	}
            	//If selected
            	if( updateBill_ ){
            		if(newQuantite_ == -1){
            			//No quantity has been specified => We set to to default quantity
            			newQuantite_ = oldQuantite_;
            		}
            		if(newQuantiteUnitEnum_ == null ){
            			//No quantity unit specified => We set to to default quantity unit
            			newQuantiteUnitEnum_ = oldQuantiteUnitEnum_;
            		}
            		//We update the quantity 
            		
            		Quantity q = new Quantity();
            		q.setUnit( newQuantiteUnitEnum_.name() );
            		q.setValue(newQuantite_);
            		oppi.setQuantity(q);
            	} else {
            		//We remove it
            		op.getOrderPartProductItems().remove(oppi);
            	}
			}
			
			@Override
			public void onClick(ClickEvent event) {
				if( form.validate() ){
					try{
						Float newQuantite = tiUserQuantity.getValueAsFloat();
						String newQuantiteUnit = fiUserQuantityUnit.getValue().toString();
						Unit newQuantiteUnitEnum = Unit.fromDisplayName( newQuantiteUnit );
						
						float oldPrice = computeOldPrice();
						Float oldQuantite = product==null?null:product.getPrice().getQuantity().getValue();
						Unit oldQuantiteUnitEnum = product==null?null:product.getPrice().getQuantity().getUnitAsEnum();
						
						updateOrder(oldQuantiteUnitEnum, newQuantiteUnitEnum, newQuantite, oldQuantite);
		            	
		            	float totalRecordPrice = computePrice(oldQuantiteUnitEnum, newQuantiteUnitEnum,
		    					newQuantite, oldQuantite, oldPrice);
		            			            	
		            	EventBusManager.getInstance().getEventBus().fireEvent(
		                			new CustomerOrderChangedEvent(updateBill_ , totalRecordPrice));
		            	updateProduct(updateBill_);
		            	
		            	saveOnServer();
		            	ProductCustomerEditionWindow.this.destroy();
					} catch(Exception e_){
						GWT.log("Basket outside panel : onEditComplete ", e_);
					}
//					ProductCustomerEditionWindow.this.destroy();
				}
            }
		};
	}

	protected float computeOldPrice() {
		float oldPrice = 0.0f;
		if(oldOppi!=null){
			float userQuantity = oldOppi.getQuantity().getValue();
			float price = oldOppi.getOnSaleProduct().getPrice().getAmount();
			
			String userQuantiteUnit = oldOppi.getQuantity().getUnit();
			String unit = oldOppi.getOnSaleProduct().getPrice().getQuantity().getUnit();
			
			float coef = 1.0f;
	    	if(unit.equalsIgnoreCase(Unit.KG.name()) 
	    			&& userQuantiteUnit.equalsIgnoreCase(Unit.G.name())){
	    		coef = 1/1000f;
	    	} else if (unit.equalsIgnoreCase(Unit.G.name()) 
	    			&& userQuantiteUnit.equalsIgnoreCase(Unit.KG.name())){
	    		coef = 1000f;
	    	}
	    	
	    	oldPrice = price*userQuantity*coef/oldOppi.getOnSaleProduct().getPrice().getQuantity().getValue();
		}
		
		return oldPrice;
	}
	
	private void updateProduct(boolean addToChart_){
		Element e = DOM.getElementById("shoppingChartGreen." + product.getProduct().getName());
    	if( addToChart_ ){
    		e.addClassName("productInChartGreen");
		} else {
			e.removeClassName("productInChartGreen");
		}
	}
	
	private void saveOnServer(){
		RPCCallSequencer callSequencer = new RPCCallSequencer("Enregistrement en cours...");
		final SaveStallCallback saveStallCallback = new SaveStallCallback(stall);
		callSequencer.addCall(saveStallCallback);
		callSequencer.addRunnable(new Runnable() {
			public void run() {
//				onDataOnServerChanged.execute();
			}
		});
		callSequencer.callSequence();
	}
}
